﻿// --------------------------------
// <copyright file="EntityDataModelOrderRepository.cs" company="private">
//     Microsoft Public License (Ms-PL)
// </copyright>
// <author>Glenn</author>
// ---------------------------------

using System.Collections.Generic;
using System.Linq;
using OpenTicket.Model;
using OpenTicket.Repositories.Entitymodel;
using Order = OpenTicket.Model.Order;
using Product = OpenTicket.Model.Product;

namespace OpenTicket.Repositories
{
    /// <summary>
    /// Repository for Orders connected to ADO.NET Entity Framework
    /// </summary>
    public class EntityDataModelOrderRepository : EntityDataModelRepositoryBase, IOrderRepository
    {
        #region IOrderRepository Members

        /// <summary>
        /// Gets all Orders from persistance
        /// </summary>
        /// <returns>All Orders</returns>
        public IQueryable<Order> GetAllOrders()
        {
            return from order in Edm.Order.Include("OrderItem")
                   select new Order
                              {
                                  OrderId = order.OrderId,
                                  CreatedDate = order.CreatedDate,
                                  OrderRows = from orderItem in order.OrderItem
                                              select new OrderRow
                                                         {
                                                             Amount = orderItem.Amount,
                                                             OrderId = order.OrderId,
                                                             Product =
                                                                 new Product
                                                                     {
                                                                         ProductCode = orderItem.ProductCode,
                                                                         ProductCost = orderItem.ProductCost,
                                                                         ProductName = orderItem.ProductName
                                                                     }
                                                         }
                              };
        }

        /// <summary>
        /// Saves a Order object to persistance
        /// </summary>
        /// <param name="order">The Order to save</param>
        /// <returns>The saved Order (with Id on insert)</returns>
        public Order Save(Order order)
        {
            Entitymodel.Order orderEntity =
                Edm.Order.Include("OrderItem").Where(x => x.OrderId == order.OrderId).FirstOrDefault();
            bool isNew = false;

            if (orderEntity == null)
            {
                orderEntity = new Entitymodel.Order();
                orderEntity.OrderId = order.OrderId;
                isNew = true;
            }

            this.PopulateOrderEntity(order, orderEntity);
            if (isNew)
            {
                Edm.AddToOrder(orderEntity);
            }

            Edm.SaveChanges();

            return order;
        }

        /// <summary>
        /// Deletes the order.
        /// </summary>
        /// <param name="order">The order.</param>
        public void DeleteOrder(Order order)
        {
            Entitymodel.Order orderEntity = Edm.Order.Where(x => x.OrderId == order.OrderId).FirstOrDefault();

            ////THINKOF:Maybe compare here to see if product has changed since loaded last time

            Edm.DeleteObject(orderEntity);
            Edm.SaveChanges();
        }

        #endregion

        /// <summary>
        /// Populates the order entity with orderitems and delete inactual orderitems.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <param name="orderEntity">The order entity.</param>
        /// <returns>The Saved Order</returns>
        private Entitymodel.Order PopulateOrderEntity(Order order, Entitymodel.Order orderEntity)
        {
            orderEntity.CreatedDate = order.CreatedDate;

            IEnumerable<OrderItem> items = from item in orderEntity.OrderItem
                                           where !(from p in order.OrderRows
                                                   select p.Product.ProductCode).Contains(item.ProductCode)
                                           select item;
            foreach (OrderItem item in items)
            {
                Edm.DeleteObject(item);
            }

            foreach (OrderItem orderItemEntity in orderEntity.OrderItem)
            {
                OrderItem tmp = orderItemEntity;
                OrderRow orderItem =
                    (from o in order.OrderRows where o.Product.ProductCode == tmp.ProductCode select o).FirstOrDefault();

                // if the quantity has changed, update it
                if (orderItem != null && orderItemEntity.Amount != orderItem.Amount)
                {
                    orderItemEntity.Amount = orderItem.Amount;
                }
            }

            foreach (OrderRow orderRow in order.OrderRows)
            {
                OrderRow tmp = orderRow;
                OrderItem orderItemEntity =
                    (from o in orderEntity.OrderItem where o.ProductCode == tmp.Product.ProductCode select o).
                        FirstOrDefault();

                // if the product don´t exist add it
                if (orderItemEntity == null)
                {
                    Edm.AddToOrderItem(new OrderItem
                                           {
                                               Amount = orderRow.Amount,
                                               Order = orderEntity,
                                               OrderId = orderEntity.OrderId,
                                               ProductCode = orderRow.Product.ProductCode,
                                               ProductCost = orderRow.Product.ProductCost,
                                               ProductName = orderRow.Product.ProductName,
                                               Product =
                                                   Edm.Product.Where(x => x.ProductCode == tmp.Product.ProductCode).
                                                   FirstOrDefault()
                                           });
                }
            }

            return orderEntity;
        }
    }
}